The coronavirus (Covid-19) outbreaks that led to a serious health crisis has brought major disruptions on the economy in many countries, including Indonesia. Firstly identified in early March 2020, the pandemic has started to affect Indonesian economy in Q1-2020. Yet the situation is even worse in Q2-2020. How bad is that? This publication is intended to explore the economic impacts of Covid-19 pandemic across Indonesian provinces from Q1 to Q2-2020. Apart from Covid-19 cases and economic growth data, we also include jobs and community mobility data from Google to capture the impact of Covid-19 outbreaks on regional employment and people mobility.

Suggested Citation:

Harry, A. Cani, R.M, Mendez, C (2020). Covid-19 pandemic and its economic impacts: An interactive exploration on Indonesian provincial data. Available at https://rpubs.com/haginta/covid19-econ-impacts-indonesia.

This work is licensed under the Creative Commons Attribution-Share Alike 4.0 International License.

knitr::opts_chunk$set(echo = TRUE, warning=FALSE)

library(tidyverse)  # Modern data science workflow
library(sf)         # Simple features for R
library(tmap)       # Thematic Maps
library(tmaptools)  # Thematic Maps Tools
library(RColorBrewer) # ColorBrewer Palettes
library(leaflet)    # Interactive web maps
library(rgdal)      # Bindings for the Geospatial Data Abstraction Library
library(rgeos)      # Interface to Geometry Engine - Open Source 


# Change the presentation of decimal numbers to 4 and avoid scientific notation
options(prompt="R> ", digits=4, scipen=999)

1 Load non-spatial data

library(readxl)
data <- read_excel("explore expandr.xlsx", 
    sheet = "Sheet1")
View(data)
df <- data %>% select(-c(4:7,9:12))

2 Load dataframe of definitions

library(readr)
df_definitions <- read_delim("df_def.csv", ";", escape_double = FALSE, 
    trim_ws = TRUE)
Parsed with column specification:
cols(
  var_name = col_character(),
  var_def = col_character(),
  source = col_character(),
  type = col_character()
)
df_definitions

3 Load shape file of Indonesian provinces

map <- read_sf("province border.shp")

4 Merge non-spatial data with spatial data

covid_map <- inner_join(
  df,
  map,
  by = "ID"
)
covid_map

5 Store data as sf object

covid_map1 <- st_as_sf(covid_map)
case_rate <- ggplot(data, aes(reorder(province, -rate_chg, sum), rate_chg)) +
  geom_col() + coord_flip() +
  theme_minimal() +
labs(subtitle = "",
x = "Province",
y = "Change in number of cases (in 100.000 population)", color="grey") +
theme(text=element_text( family="Palatino")) + 
  theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
panel.background = element_blank(), axis.line = element_line(colour = "black"))
  guides(col = guide_legend(nrow = 8))
$colour
$title
list()
attr(,"class")
[1] "waiver"

$title.position
NULL

$title.theme
NULL

$title.hjust
NULL

$title.vjust
NULL

$label
[1] TRUE

$label.position
NULL

$label.theme
NULL

$label.hjust
NULL

$label.vjust
NULL

$keywidth
NULL

$keyheight
NULL

$direction
NULL

$override.aes
named list()

$nrow
[1] 8

$ncol
NULL

$byrow
[1] FALSE

$reverse
[1] FALSE

$order
[1] 0

$available_aes
[1] "any"

$name
[1] "legend"

attr(,"class")
[1] "guide"  "legend"

attr(,"class")
[1] "guides"
case_rate
ggsave("case_change.png", width = 9, height = 5)

a <- data %>% mutate(gdp_col = ifelse(gdp_q2_yoy < 0, "red", "green")) 
  ggplot(a, aes(reorder(province, -gdp_q2_yoy, sum), gdp_q2_yoy, fill = gdp_col)) +
  geom_col() + coord_flip() +   scale_fill_identity(guide = FALSE) +
  theme_minimal() +
labs(subtitle = "",
x = "Province",
y = "GDP growth in Q2-2020 (%, yoy)", color="grey") +
theme(text=element_text( family="Palatino")) + 
  theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
panel.background = element_blank(), axis.line = element_line(colour = "black"))
  guides(col = guide_legend(nrow = 8))
$colour
$title
list()
attr(,"class")
[1] "waiver"

$title.position
NULL

$title.theme
NULL

$title.hjust
NULL

$title.vjust
NULL

$label
[1] TRUE

$label.position
NULL

$label.theme
NULL

$label.hjust
NULL

$label.vjust
NULL

$keywidth
NULL

$keyheight
NULL

$direction
NULL

$override.aes
named list()

$nrow
[1] 8

$ncol
NULL

$byrow
[1] FALSE

$reverse
[1] FALSE

$order
[1] 0

$available_aes
[1] "any"

$name
[1] "legend"

attr(,"class")
[1] "guide"  "legend"

attr(,"class")
[1] "guides"
ggsave("gdp_q2.png", width = 9, height = 5)

mobility <- ggplot(data, aes(reorder(province, -mob_all, sum), mob_all)) +
  geom_col() + coord_flip() +
  theme_minimal() +
labs(subtitle = "",
x = "Province",
y = "Change in people mobility relative to baseline", color="grey") +
theme(text=element_text( family="Palatino")) + 
  theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
panel.background = element_blank(), axis.line = element_line(colour = "black"))
  guides(col = guide_legend(nrow = 8))
$colour
$title
list()
attr(,"class")
[1] "waiver"

$title.position
NULL

$title.theme
NULL

$title.hjust
NULL

$title.vjust
NULL

$label
[1] TRUE

$label.position
NULL

$label.theme
NULL

$label.hjust
NULL

$label.vjust
NULL

$keywidth
NULL

$keyheight
NULL

$direction
NULL

$override.aes
named list()

$nrow
[1] 8

$ncol
NULL

$byrow
[1] FALSE

$reverse
[1] FALSE

$order
[1] 0

$available_aes
[1] "any"

$name
[1] "legend"

attr(,"class")
[1] "guide"  "legend"

attr(,"class")
[1] "guides"
mobility
ggsave("mobility.png", width = 9, height = 5)

job_loss <- ggplot(data, aes(reorder(province, -job_loss, sum), job_loss)) +
  geom_col() + coord_flip() +
  theme_minimal() +
labs(subtitle = "",
x = "Province",
y = "Number of people who loss their job", color="grey") +
theme(text=element_text( family="Palatino")) + 
  theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
panel.background = element_blank(), axis.line = element_line(colour = "black"))
  guides(col = guide_legend(nrow = 8))
$colour
$title
list()
attr(,"class")
[1] "waiver"

$title.position
NULL

$title.theme
NULL

$title.hjust
NULL

$title.vjust
NULL

$label
[1] TRUE

$label.position
NULL

$label.theme
NULL

$label.hjust
NULL

$label.vjust
NULL

$keywidth
NULL

$keyheight
NULL

$direction
NULL

$override.aes
named list()

$nrow
[1] 8

$ncol
NULL

$byrow
[1] FALSE

$reverse
[1] FALSE

$order
[1] 0

$available_aes
[1] "any"

$name
[1] "legend"

attr(,"class")
[1] "guide"  "legend"

attr(,"class")
[1] "guides"
job_loss
ggsave("job_loss.png", width = 9, height = 5)

#Correlation matrix

df1 <- subset(data, select = c(2, 13, 15, 22, 23, 25))
  colnames(df1) <- c("Province", "Case change", "Job loss", "People mobility", "TAS share in GDP", "GDPg Q2-2020")
# Provide correlation matrix
corr <- cor(df1[,c(2:6)])
round(corr, 2)
                 Case change Job loss People mobility TAS share in GDP
Case change             1.00     0.18           -0.37             0.36
Job loss                0.18     1.00           -0.03             0.25
People mobility        -0.37    -0.03            1.00            -0.67
TAS share in GDP        0.36     0.25           -0.67             1.00
GDPg Q2-2020           -0.04    -0.52            0.30            -0.59
                 GDPg Q2-2020
Case change             -0.04
Job loss                -0.52
People mobility          0.30
TAS share in GDP        -0.59
GDPg Q2-2020             1.00
flattenCorrMatrix <- function(cormat, pmat) {
  ut <- upper.tri(cormat)
  data.frame(
    row = rownames(cormat)[row(cormat)[ut]],
    column = rownames(cormat)[col(cormat)[ut]],
    cor  =(cormat)[ut],
    p = pmat[ut]
    )
}
library(Hmisc)
res2<-rcorr(as.matrix(df1[,c(2:6)]))
flattenCorrMatrix(res2$r, res2$P)
# Visualize correlation matrix
library(corrplot)
corrplot(res2$r, type="upper", order="hclust", 
         p.mat = res2$P, sig.level = 0.05, insig = "label_sig")
dev.copy(jpeg,filename="corr.png");
jpeg 
   3 
dev.off ();
png 
  2 

LS0tDQp0aXRsZTogIkNvdmlkLTE5IHBhbmRlbWljIGFuZCBpdHMgZWNvbm9taWMgaW1wYWN0czogQW4gaW50ZXJhY3RpdmUgZXhwbG9yYXRpb24gb24gSW5kb25lc2lhbiBwcm92aW5jaWFsIGRhdGEiDQphdXRob3I6ICJIYXJyeSBBZ2ludGEsIFJhZ2RhZCBDYW5pIE1pcmFudGksIENhcmxvcyBNZW5kZXoiDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6DQogICAgY29kZV9mb2xkaW5nOiBzaG93DQogICAgaGlnaGxpZ2h0OiBtb25vY2hyb21lDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICB0aGVtZTogY29zbW8NCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIHRvY19mbG9hdDoNCiAgICAgIGNvbGxhcHNlZDogbm8NCiAgICAgIHNtb290aF9zY3JvbGw6IG5vDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIGRmX3ByaW50OiBwYWdlZA0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19mbG9hdDoNCiAgICAgIGNvbGxhcHNlZDogZmFsc2UNCiAgICAgIHNtb290aF9zY3JvbGw6IGZhbHNlDQogICAgdG9jX2RlcHRoOiA0DQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQogICAgY29kZV9mb2xkaW5nOiAic2hvdyINCiAgICB0aGVtZTogImNvc21vIg0KICAgIGhpZ2hsaWdodDogIm1vbm9jaHJvbWUiDQogIHBkZl9kb2N1bWVudDogZGVmYXVsdA0KICB3b3JkX2RvY3VtZW50OiBkZWZhdWx0DQotLS0NCg0KDQo8c3R5bGU+DQpoMS50aXRsZSB7Zm9udC1zaXplOiAxOHB0OyBjb2xvcjogRGFya0JsdWU7fSANCmJvZHksIGgxLCBoMiwgaDMsIGg0IHtmb250LWZhbWlseTogIlBhbGF0aW5vIiwgc2VyaWY7fQ0KYm9keSB7Zm9udC1zaXplOiAxMnB0O30NCi8qIEhlYWRlcnMgKi8NCmgxLGgyLGgzLGg0LGg1LGg2e2ZvbnQtc2l6ZTogMTRwdDsgY29sb3I6ICMwMDAwOEI7fQ0KYm9keSB7Y29sb3I6ICMzMzMzMzM7fQ0KYSwgYTpob3ZlciB7Y29sb3I6ICM4QjNBNjI7fQ0KcHJlIHtmb250LXNpemU6IDEycHg7fQ0KPC9zdHlsZT4NCg0KVGhlIGNvcm9uYXZpcnVzIChDb3ZpZC0xOSkgb3V0YnJlYWtzIHRoYXQgbGVkIHRvIGEgc2VyaW91cyBoZWFsdGggY3Jpc2lzIGhhcyBicm91Z2h0IG1ham9yIGRpc3J1cHRpb25zIG9uIHRoZSBlY29ub215IGluIG1hbnkgY291bnRyaWVzLCBpbmNsdWRpbmcgSW5kb25lc2lhLiBGaXJzdGx5IGlkZW50aWZpZWQgaW4gZWFybHkgTWFyY2ggMjAyMCwgdGhlIHBhbmRlbWljIGhhcyBzdGFydGVkIHRvIGFmZmVjdCBJbmRvbmVzaWFuIGVjb25vbXkgaW4gUTEtMjAyMC4gWWV0IHRoZSBzaXR1YXRpb24gaXMgZXZlbiB3b3JzZSBpbiBRMi0yMDIwLiBIb3cgYmFkIGlzIHRoYXQ/IFRoaXMgcHVibGljYXRpb24gaXMgaW50ZW5kZWQgdG8gZXhwbG9yZSB0aGUgZWNvbm9taWMgaW1wYWN0cyBvZiBDb3ZpZC0xOSBwYW5kZW1pYyBhY3Jvc3MgSW5kb25lc2lhbiBwcm92aW5jZXMgZnJvbSBRMSB0byBRMi0yMDIwLiBBcGFydCBmcm9tIENvdmlkLTE5IGNhc2VzIGFuZCBlY29ub21pYyBncm93dGggZGF0YSwgd2UgYWxzbyBpbmNsdWRlIGpvYnMgYW5kIGNvbW11bml0eSBtb2JpbGl0eSBkYXRhIGZyb20gR29vZ2xlIHRvIGNhcHR1cmUgdGhlIGltcGFjdCBvZiBDb3ZpZC0xOSBvdXRicmVha3Mgb24gcmVnaW9uYWwgZW1wbG95bWVudCBhbmQgcGVvcGxlIG1vYmlsaXR5Lg0KDQpTdWdnZXN0ZWQgQ2l0YXRpb246IA0KDQo+IEhhcnJ5LCBBLiBDYW5pLCBSLk0sIE1lbmRleiwgQyAoMjAyMCkuIF9Db3ZpZC0xOSBwYW5kZW1pYyBhbmQgaXRzIGVjb25vbWljIGltcGFjdHM6IEFuIGludGVyYWN0aXZlIGV4cGxvcmF0aW9uIG9uIEluZG9uZXNpYW4gcHJvdmluY2lhbCBkYXRhLl8gQXZhaWxhYmxlIGF0IGh0dHBzOi8vcnB1YnMuY29tL2hhZ2ludGEvY292aWQxOS1lY29uLWltcGFjdHMtaW5kb25lc2lhLg0KDQpUaGlzIHdvcmsgaXMgbGljZW5zZWQgdW5kZXIgdGhlIENyZWF0aXZlIENvbW1vbnMgQXR0cmlidXRpb24tU2hhcmUgQWxpa2UgNC4wIEludGVybmF0aW9uYWwgTGljZW5zZS4gDQohW10oQ0NMaWNlbnNlLnBuZyl7d2lkdGg9NzVweH0NCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgd2FybmluZz1GQUxTRSkNCg0KbGlicmFyeSh0aWR5dmVyc2UpICAjIE1vZGVybiBkYXRhIHNjaWVuY2Ugd29ya2Zsb3cNCmxpYnJhcnkoc2YpICAgICAgICAgIyBTaW1wbGUgZmVhdHVyZXMgZm9yIFINCmxpYnJhcnkodG1hcCkgICAgICAgIyBUaGVtYXRpYyBNYXBzDQpsaWJyYXJ5KHRtYXB0b29scykgICMgVGhlbWF0aWMgTWFwcyBUb29scw0KbGlicmFyeShSQ29sb3JCcmV3ZXIpICMgQ29sb3JCcmV3ZXIgUGFsZXR0ZXMNCmxpYnJhcnkobGVhZmxldCkgICAgIyBJbnRlcmFjdGl2ZSB3ZWIgbWFwcw0KbGlicmFyeShyZ2RhbCkgICAgICAjIEJpbmRpbmdzIGZvciB0aGUgR2Vvc3BhdGlhbCBEYXRhIEFic3RyYWN0aW9uIExpYnJhcnkNCmxpYnJhcnkocmdlb3MpICAgICAgIyBJbnRlcmZhY2UgdG8gR2VvbWV0cnkgRW5naW5lIC0gT3BlbiBTb3VyY2UgDQoNCg0KIyBDaGFuZ2UgdGhlIHByZXNlbnRhdGlvbiBvZiBkZWNpbWFsIG51bWJlcnMgdG8gNCBhbmQgYXZvaWQgc2NpZW50aWZpYyBub3RhdGlvbg0Kb3B0aW9ucyhwcm9tcHQ9IlI+ICIsIGRpZ2l0cz00LCBzY2lwZW49OTk5KQ0KYGBgDQoNCg0KIyBMb2FkIG5vbi1zcGF0aWFsIGRhdGENCg0KYGBge3J9DQpsaWJyYXJ5KHJlYWR4bCkNCmRhdGEgPC0gcmVhZF9leGNlbCgiZXhwbG9yZSBleHBhbmRyLnhsc3giLCANCiAgICBzaGVldCA9ICJTaGVldDEiKQ0KVmlldyhkYXRhKQ0KYGBgDQoNCmBgYHtyfQ0KZGYgPC0gZGF0YSAlPiUgc2VsZWN0KC1jKDQ6Nyw5OjEyKSkNCmBgYA0KDQojIExvYWQgZGF0YWZyYW1lIG9mIGRlZmluaXRpb25zDQpgYGB7cn0NCmxpYnJhcnkocmVhZHIpDQpkZl9kZWZpbml0aW9ucyA8LSByZWFkX2RlbGltKCJkZl9kZWYuY3N2IiwgIjsiLCBlc2NhcGVfZG91YmxlID0gRkFMU0UsIA0KICAgIHRyaW1fd3MgPSBUUlVFKQ0KZGZfZGVmaW5pdGlvbnMNCmBgYA0KDQojIExvYWQgc2hhcGUgZmlsZSBvZiBJbmRvbmVzaWFuIHByb3ZpbmNlcw0KYGBge3J9DQptYXAgPC0gcmVhZF9zZigicHJvdmluY2UgYm9yZGVyLnNocCIpDQpgYGANCg0KIyBNZXJnZSBub24tc3BhdGlhbCBkYXRhIHdpdGggc3BhdGlhbCBkYXRhDQpgYGB7cn0NCmNvdmlkX21hcCA8LSBpbm5lcl9qb2luKA0KICBkZiwNCiAgbWFwLA0KICBieSA9ICJJRCINCikNCmBgYA0KDQpgYGB7cn0NCmNvdmlkX21hcA0KYGBgDQoNCiMgU3RvcmUgZGF0YSBhcyBzZiBvYmplY3QNCmBgYHtyfQ0KY292aWRfbWFwMSA8LSBzdF9hc19zZihjb3ZpZF9tYXApDQpgYGANCg0KYGBge3J9DQpjYXNlX3JhdGUgPC0gZ2dwbG90KGRhdGEsIGFlcyhyZW9yZGVyKHByb3ZpbmNlLCAtcmF0ZV9jaGcsIHN1bSksIHJhdGVfY2hnKSkgKw0KICBnZW9tX2NvbCgpICsgY29vcmRfZmxpcCgpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCmxhYnMoc3VidGl0bGUgPSAiIiwNCnggPSAiUHJvdmluY2UiLA0KeSA9ICJDaGFuZ2UgaW4gbnVtYmVyIG9mIGNhc2VzIChpbiAxMDAuMDAwIHBvcHVsYXRpb24pIiwgY29sb3I9ImdyZXkiKSArDQp0aGVtZSh0ZXh0PWVsZW1lbnRfdGV4dCggZmFtaWx5PSJQYWxhdGlubyIpKSArIA0KICB0aGVtZShwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLA0KcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJibGFjayIpKQ0KICBndWlkZXMoY29sID0gZ3VpZGVfbGVnZW5kKG5yb3cgPSA4KSkNCmNhc2VfcmF0ZQ0KZ2dzYXZlKCJjYXNlX2NoYW5nZS5wbmciLCB3aWR0aCA9IDksIGhlaWdodCA9IDUpDQpgYGANCg0KYGBge3J9DQphIDwtIGRhdGEgJT4lIG11dGF0ZShnZHBfY29sID0gaWZlbHNlKGdkcF9xMl95b3kgPCAwLCAicmVkIiwgImdyZWVuIikpIA0KICBnZ3Bsb3QoYSwgYWVzKHJlb3JkZXIocHJvdmluY2UsIC1nZHBfcTJfeW95LCBzdW0pLCBnZHBfcTJfeW95LCBmaWxsID0gZ2RwX2NvbCkpICsNCiAgZ2VvbV9jb2woKSArIGNvb3JkX2ZsaXAoKSArICAgc2NhbGVfZmlsbF9pZGVudGl0eShndWlkZSA9IEZBTFNFKSArDQogIHRoZW1lX21pbmltYWwoKSArDQpsYWJzKHN1YnRpdGxlID0gIiIsDQp4ID0gIlByb3ZpbmNlIiwNCnkgPSAiR0RQIGdyb3d0aCBpbiBRMi0yMDIwICglLCB5b3kpIiwgY29sb3I9ImdyZXkiKSArDQp0aGVtZSh0ZXh0PWVsZW1lbnRfdGV4dCggZmFtaWx5PSJQYWxhdGlubyIpKSArIA0KICB0aGVtZShwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLA0KcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJibGFjayIpKQ0KICBndWlkZXMoY29sID0gZ3VpZGVfbGVnZW5kKG5yb3cgPSA4KSkNCmdnc2F2ZSgiZ2RwX3EyLnBuZyIsIHdpZHRoID0gOSwgaGVpZ2h0ID0gNSkNCmBgYA0KDQpgYGB7cn0NCm1vYmlsaXR5IDwtIGdncGxvdChkYXRhLCBhZXMocmVvcmRlcihwcm92aW5jZSwgLW1vYl9hbGwsIHN1bSksIG1vYl9hbGwpKSArDQogIGdlb21fY29sKCkgKyBjb29yZF9mbGlwKCkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KbGFicyhzdWJ0aXRsZSA9ICIiLA0KeCA9ICJQcm92aW5jZSIsDQp5ID0gIkNoYW5nZSBpbiBwZW9wbGUgbW9iaWxpdHkgcmVsYXRpdmUgdG8gYmFzZWxpbmUiLCBjb2xvcj0iZ3JleSIpICsNCnRoZW1lKHRleHQ9ZWxlbWVudF90ZXh0KCBmYW1pbHk9IlBhbGF0aW5vIikpICsgDQogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksDQpwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImJsYWNrIikpDQogIGd1aWRlcyhjb2wgPSBndWlkZV9sZWdlbmQobnJvdyA9IDgpKQ0KbW9iaWxpdHkNCmdnc2F2ZSgibW9iaWxpdHkucG5nIiwgd2lkdGggPSA5LCBoZWlnaHQgPSA1KQ0KYGBgDQoNCmBgYHtyfQ0Kam9iX2xvc3MgPC0gZ2dwbG90KGRhdGEsIGFlcyhyZW9yZGVyKHByb3ZpbmNlLCAtam9iX2xvc3MsIHN1bSksIGpvYl9sb3NzKSkgKw0KICBnZW9tX2NvbCgpICsgY29vcmRfZmxpcCgpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCmxhYnMoc3VidGl0bGUgPSAiIiwNCnggPSAiUHJvdmluY2UiLA0KeSA9ICJOdW1iZXIgb2YgcGVvcGxlIHdobyBsb3NzIHRoZWlyIGpvYiIsIGNvbG9yPSJncmV5IikgKw0KdGhlbWUodGV4dD1lbGVtZW50X3RleHQoIGZhbWlseT0iUGFsYXRpbm8iKSkgKyANCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwNCnBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siKSkNCiAgZ3VpZGVzKGNvbCA9IGd1aWRlX2xlZ2VuZChucm93ID0gOCkpDQpqb2JfbG9zcw0KZ2dzYXZlKCJqb2JfbG9zcy5wbmciLCB3aWR0aCA9IDksIGhlaWdodCA9IDUpDQpgYGANCg0KDQojQ29ycmVsYXRpb24gbWF0cml4DQoNCmBgYHtyfQ0KZGYxIDwtIHN1YnNldChkYXRhLCBzZWxlY3QgPSBjKDIsIDEzLCAxNSwgMjIsIDIzLCAyNSkpDQogIGNvbG5hbWVzKGRmMSkgPC0gYygiUHJvdmluY2UiLCAiQ2FzZSBjaGFuZ2UiLCAiSm9iIGxvc3MiLCAiUGVvcGxlIG1vYmlsaXR5IiwgIlRBUyBzaGFyZSBpbiBHRFAiLCAiR0RQZyBRMi0yMDIwIikNCmBgYA0KDQoNCmBgYHtyfQ0KIyBQcm92aWRlIGNvcnJlbGF0aW9uIG1hdHJpeA0KY29yciA8LSBjb3IoZGYxWyxjKDI6NildKQ0Kcm91bmQoY29yciwgMikNCmBgYA0KDQpgYGB7cn0NCmZsYXR0ZW5Db3JyTWF0cml4IDwtIGZ1bmN0aW9uKGNvcm1hdCwgcG1hdCkgew0KICB1dCA8LSB1cHBlci50cmkoY29ybWF0KQ0KICBkYXRhLmZyYW1lKA0KICAgIHJvdyA9IHJvd25hbWVzKGNvcm1hdClbcm93KGNvcm1hdClbdXRdXSwNCiAgICBjb2x1bW4gPSByb3duYW1lcyhjb3JtYXQpW2NvbChjb3JtYXQpW3V0XV0sDQogICAgY29yICA9KGNvcm1hdClbdXRdLA0KICAgIHAgPSBwbWF0W3V0XQ0KICAgICkNCn0NCmBgYA0KDQoNCmBgYHtyfQ0KbGlicmFyeShIbWlzYykNCnJlczI8LXJjb3JyKGFzLm1hdHJpeChkZjFbLGMoMjo2KV0pKQ0KZmxhdHRlbkNvcnJNYXRyaXgocmVzMiRyLCByZXMyJFApDQpgYGANCg0KDQpgYGB7cn0NCiMgVmlzdWFsaXplIGNvcnJlbGF0aW9uIG1hdHJpeA0KbGlicmFyeShjb3JycGxvdCkNCmNvcnJwbG90KHJlczIkciwgdHlwZT0idXBwZXIiLCBvcmRlcj0iaGNsdXN0IiwgDQogICAgICAgICBwLm1hdCA9IHJlczIkUCwgc2lnLmxldmVsID0gMC4wNSwgaW5zaWcgPSAibGFiZWxfc2lnIikNCmRldi5jb3B5KGpwZWcsZmlsZW5hbWU9ImNvcnIucG5nIik7DQpkZXYub2ZmICgpOw0KYGBg